import { isUndefined, hasOwn } from './helpers'

/**
 * 合并对象
 * @param target
 * @param sources
 */

export function extend(
  target: Record<string, unknown>,
  ...sources: Record<string, unknown>[]
): Record<string, unknown> {
  for (const source of sources) {
    if (isUndefined(source)) continue
    for (const key of Object.keys(source)) {
      target[key] = source[key]
    }
  }

  return target
}

/**
 * 仅对目标对象已有的属性赋值
 * @param target
 * @param source
 * @param ignoreUndefined 是否忽略空值(null/undefined)
 */
export function copy(target: Record<string, unknown>, source: Record<string, unknown>, ignoreUndefined = false): void {
  if (isUndefined(source)) return
  source = deepClone(source)
  for (const key of Object.keys(target)) {
    if (hasOwn(source, key)) {
      if (ignoreUndefined && isUndefined(source[key])) return
      target[key] = source[key]
    }
  }
}

/**
 * 深拷贝
 * @param source 要拷贝的数据
 */
export function deepClone(source: any): any {
  return JSON.parse(JSON.stringify(source))
}

/**
 * 列表转为树形解构数据
 * @param data 要转换的数据
 * @param pidName 父级ID字段
 * @param childrenName 子级名称
 */
export function listToTree(data: any[], pidName = 'parent_id', childrenName = 'children'): any[] {
  if (data.length === 0) {
    return []
  }

  const temp: any = {}
  const tree: any[] = []

  for (const item of data) {
    temp[item.id] = item
  }

  for (const key in temp) {
    const parentId = temp[key][pidName]
    // temp[key][childrenName] = [] // 所有item都添加children
    if (parentId in temp) {
      //仅给有子项的item添加children
      if (!temp[parentId][childrenName]) {
        temp[parentId][childrenName] = []
      }
      temp[parentId].children.push(temp[key])
    } else {
      tree.push(temp[key])
    }
  }

  return tree
}

/**
 * 从列表中提取指定列数据
 * @param userMenus
 * @param column
 * @returns
 */
export function listToColumn<T = unknown>(list: any[], column: string): T[] {
  const data: T[] = []

  list.forEach((item) => {
    if (hasOwn(item, column)) {
      data.push(item[column])
    }
  })

  return data
}

/**
 * 防抖
 * @param fn 要包装的函数
 * @param delay 延时
 */
export function debounce(fn: any, delay = 500): (...args: any) => void {
  let timer: number | undefined
  return function (...args: any) {
    window.clearTimeout(timer)
    timer = window.setTimeout(() => {
      fn(...args)
    }, delay)
  }
}

/**
 * 节流
 * @param fn 要包装的函数
 * @param delay 延时
 */
export function throttle(fn: any, delay = 500): (...args: any) => void {
  let flag = true
  return function (...args: any) {
    if (flag) {
      window.setTimeout(() => {
        fn(...args)
        flag = true
      }, delay)
    }
    flag = false
  }
}
